home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Documentation / DirectX9 / directplay.chm / code / xslutil.js < prev   
Encoding:
Text File  |  2004-09-27  |  39.5 KB  |  1,495 lines

  1. <![CDATA[
  2.  
  3.   // simple context object that caches project-specific settings defined in settings.dtd
  4.   function CContext(oDoc, sDevLang, sMedia, sExt, sProj, sProjMask, sDefPlat, iAllowSelfUnregistered, iLuCache, iUseTargetsV2) //at //markda
  5.   {
  6.     this._oDoc = oDoc; // cache a reference to the current XML document
  7.     this._devlang = sDevLang;
  8.     this._media = sMedia;
  9.     this._ext = sExt;
  10.     this._proj = sProj
  11.     this._projMask = sProjMask;
  12.     this._defPlat = sDefPlat;
  13.     this._bAllowSelfUnregistered = (iAllowSelfUnregistered ? true : false);
  14.     this._paths = new Array();
  15.  
  16.     //markda: Switch that determines if targets v1 or v2 is used
  17.     this._bUseTargetsV2 = (iUseTargetsV2 ? true : false);
  18.  
  19.     //at: Switch that determines if lookup caching is done (ie, LuCache).
  20.     this._bCacheLookups = (iLuCache ? true : false);
  21.  
  22.     //at: Following code creates the target node "mini-dom" and
  23.     //at: gets local hard drive for later targets.xml path assembly.
  24.     this._oTDom = new ActiveXObject("Microsoft.XMLDOM");
  25.     var re = /\/\/.:/i;
  26.     var n = oDoc.url.search(re);
  27.     if (n > 0)
  28.     {
  29.       var sVal = oDoc.url.substr(n+2, 2);
  30.       this._sDrive = sVal.toLowerCase();
  31.     }
  32.     else
  33.       this._sDrive = "";
  34.   }
  35.  
  36.   CContext.prototype.GetPathOf = function(sKey)
  37.   {
  38.     return this._paths[sKey];
  39.   }
  40.  
  41.   CContext.prototype.SetPathOf = function(sKey, sPath)
  42.   {
  43.     this._paths[sKey] = sPath;
  44.   }
  45.  
  46.   // return a reference to the current document
  47.   CContext.prototype.GetDocument = function()
  48.   {
  49.     return this._oDoc;
  50.   }
  51.  
  52.   CContext.prototype.GetDevLang = function()
  53.   {
  54.     return this._devlang;
  55.   }
  56.  
  57.   CContext.prototype.GetDefaultPlatform = function()
  58.   {
  59.     return this._defPlat;
  60.   }
  61.  
  62.   CContext.prototype.AllowSelfUnregistered = function()
  63.   {
  64.     return this._bAllowSelfUnregistered;
  65.   }
  66.  
  67.   //at: Return true if Lookup Caching is on.
  68.   CContext.prototype.CacheLookups = function()
  69.   {
  70.     return this._bCacheLookups;
  71.   }
  72.  
  73.   //at: Force Turn off of lookup caching.
  74.   CContext.prototype.NoCacheLookups = function()
  75.   {
  76.     this._bCacheLookups = false;
  77.   }
  78.  
  79.   //markda: Return true if targets v2 required
  80.   CContext.prototype.UseTargetsV2 = function()
  81.   {
  82.     return this._bUseTargetsV2;
  83.   }
  84.  
  85.   // if an iface is marked as primary, return it
  86.   // if more than one iface is marked as primary, return the first
  87.   // if no ifaces are marked as primary, return the first
  88.   function GetActiveIFace()
  89.   {
  90.     var oActiveIFaces = ownerDocument.selectNodes("/inetsdk:topic/metadata/applies/iface[@primary]");
  91.     if (oActiveIFaces.length == 0)
  92.     {
  93.       var oActiveIFace = ownerDocument.selectSingleNode("/inetsdk:topic/metadata/applies/iface[0]");
  94.       return oActiveIFace;
  95.     }
  96.     else
  97.     {
  98.       return oActiveIFaces[0];
  99.     }
  100.   }
  101.  
  102.   // does the current topic contain at least one remark specific to the specified platform
  103.   function ContainsQualifyingRemarkForPlatform(oContainer, sDesiredPlat, sCurDLang)
  104.   {
  105.     var sDLangClause = "";
  106.     if (sCurDLang != '')
  107.     {
  108.       sDLangClause = " $and$ not(@devlang) $or$ @devlang='" + sCurDLang + "'";
  109.     }
  110.  
  111.     // ASSumes the current context is the parent of remarks
  112.     var oPotentialRems = oContainer.selectNodes("remarks/rem[@platforms" + sDLangClause + "]");
  113.     if (!oPotentialRems)
  114.     {
  115.       return false;
  116.     }
  117.  
  118.     var oRegDesiredPlat = new RegExp("\\b" + sDesiredPlat + "\\b");
  119.     for (var i = 0; i < oPotentialRems.length; i++)
  120.     {
  121.       // check to see if there's a rem specific to the specified platform
  122.       if (IsQualifyingRemarkForPlatform(oPotentialRems[i], sDesiredPlat, oRegDesiredPlat, true)  && IsQualifyingRemarkForActiveIFace(oPotentialRems[i], sCurDLang))
  123.       {
  124.         return true;
  125.       }
  126.     }
  127.  
  128.     return false;
  129.   }
  130.  
  131.   // Return true if the specified remark applies to the desired platform
  132.   // oRegDesiredPlat can be passed in as an optimization
  133.   // When set to true, bFailIfNone indicates that the rem shouldn't qualify if no platforms are specified
  134.   function IsQualifyingRemarkForPlatform(oRem, sDesiredPlat, oRegDesiredPlat, bFailIfNone)
  135.   {
  136.     var sPlatforms = oRem.getAttribute("platforms");
  137.  
  138.     if (!bFailIfNone)
  139.     {
  140.       bFailIfNone = false;
  141.     }
  142.  
  143.     // no platforms were specified
  144.     if (!sPlatforms)
  145.     {
  146.       return (bFailIfNone ? false : true);
  147.     }
  148.  
  149.     if (!oRegDesiredPlat)
  150.     {
  151.       oRegDesiredPlat = new RegExp("\\b" + sDesiredPlat + "\\b");
  152.     }
  153.  
  154.     if (oRegDesiredPlat.test(sPlatforms))
  155.     {
  156.       return true;
  157.     }
  158.  
  159.     return false;
  160.   }
  161.  
  162.   // does the topic contain any remarks that qualify
  163.   // in the script case is there a remark that's either lang-neutral or script specific
  164.   // in the cpp case is there a remark that's either lang-neutral or cpp specific. If it's cpp specific, does it pertain to the active iface
  165.   // in the vb case?
  166.   function ContainsQualifyingRemarkForDefaultPlatform(oCtx)
  167.   {
  168.     var oDoc = oCtx.GetDocument();
  169.     if (!oDoc)
  170.     {
  171.       return false;
  172.     }
  173.  
  174.     var sBaseQ = "/inetsdk:topic/content/remarks";
  175.     var sCurLang = oCtx.GetDevLang();
  176.     var sDefPlat = oCtx.GetDefaultPlatform();
  177.  
  178.     // is there a rem or a note that's devlang neutral?
  179.     var oRems = oDoc.selectNodes(sBaseQ + "/rem[not(@devlang)] | " + sBaseQ + "/note[not(@devlang)]");
  180.     if ((0 == oRems.length) && (!sCurLang || (/^\s*$/.test(sCurLang))))
  181.     {
  182.       // this is a language neutral topic that doesn't contain any neutral remarks. bail!
  183.       return false;
  184.     }
  185.  
  186.     // do one of the devlang neutral remarks qualify for the default platform?
  187.     for (var iRem = 0; iRem < oRems.length; iRem++)
  188.     {
  189.       var oRem = oRems(iRem);
  190.       // 110440: be sure to check for iface filter (@rids) since a remark can apply to any language but be restricted to
  191.       // a particular iface in the cpp case
  192.       if (IsQualifyingRemarkForPlatform(oRem, sDefPlat) && IsQualifyingRemarkForActiveIFace(oRem, sCurLang))
  193.       {
  194.         return true;
  195.       }
  196.     }
  197.  
  198.     // now deal with devlang-specific remarks
  199.     oRems = oDoc.selectNodes(sBaseQ + "/rem[@devlang='" + sCurLang + "'] | " + sBaseQ + "/note[@devlang='" + sCurLang + "']");
  200.     if (oRems.length == 0)
  201.     {
  202.       return false;
  203.     }
  204.  
  205.     // drill in to see if the rem applies to the active iface
  206.     for (iRem = 0; iRem < oRems.length; iRem++)
  207.     {
  208.       var oRem = oRems(iRem);
  209.       if (IsQualifyingRemarkForPlatform(oRem, sDefPlat) && IsQualifyingRemarkForActiveIFace(oRem, sCurLang))
  210.       {
  211.         return true;
  212.       }
  213.     }
  214.  
  215.     return false;
  216.   }
  217.  
  218.   // should the remark be included or filtered out
  219.   function IsQualifyingRemarkForActiveIFace(oRem, sCurLang)
  220.   {
  221.     var sRIDs = oRem.getAttribute("rids");
  222.     if (!sRIDs)
  223.     {
  224.       return true;
  225.     }
  226.  
  227.     if ('cpp' != sCurLang)
  228.     {
  229.       return true;
  230.     }
  231.  
  232.     var oActiveIFace = GetActiveIFace();
  233.     if (!oActiveIFace)
  234.     {
  235.       return true;
  236.     }
  237.  
  238.     var sActiveRID = oActiveIFace.getAttribute("rid");
  239.     if (!sActiveRID)
  240.     {
  241.       // Yikes! DTD should NEVER allow this to occur
  242.       return true;
  243.     }
  244.  
  245.     var oRegInList = new RegExp("\\b" + sActiveRID + "\\b");
  246.  
  247.     if (oRegInList.test(sRIDs))
  248.     {
  249.       return true;
  250.     }
  251.  
  252.     return false;
  253.  
  254.   }
  255.  
  256.   // added by chains 09/29/2000 (petertay)
  257.   // does the topic contain any params that qualify for active iface
  258.   function ContainsQualifyingParamForActiveIface(oCtx)
  259.   {
  260.  
  261.     var oDoc = oCtx.GetDocument();
  262.     if (!oDoc)
  263.     {
  264.       return false;
  265.     }
  266.  
  267.     var sBaseQ = "/inetsdk:topic/content/params";
  268.     var sCurLang = oCtx.GetDevLang();
  269.  
  270.     // is there a param that's devlang neutral?
  271.     var oParamColl = oDoc.selectNodes(sBaseQ + "/param");
  272.  
  273.     // do one of the devlang neutral remarks qualify for the active iface?
  274.     for (var iParam = 0; iParam < oParamColl.length; iParam++)
  275.     {
  276.       var oParam = oParamColl(iParam);
  277.  
  278.     // Filter out params w/autodesc and no script desc
  279.     // autodesc not currently supported in script
  280.     if (oParam.getAttribute("autodesc") && sCurLang == "scr")
  281.     {
  282.       var oScrDesc = oParam.selectNodes("desc[@devlang='scr']");
  283.     if (oScrDesc.length == 0) continue;
  284.     }
  285.       if (QualifiesForActiveIFace(oParam, sCurLang))
  286.       {
  287.         return true;
  288.       }
  289.     }
  290.  
  291.     // now deal with devlang-specific remarks
  292.     oParamColl = oDoc.selectNodes(sBaseQ + "/param[@devlang='" + sCurLang + "']");
  293.     if (oParamColl.length == 0)
  294.     {
  295.       return false;
  296.     }
  297.  
  298.     // drill in to see if the param applies to the active iface
  299.     for (iParam = 0; iParam < oParamColl.length; iParam++)
  300.     {
  301.       var oParam = oParamColl(iParam);
  302.       if (QualifiesForActiveIFace(oParam, sCurLang))
  303.       {
  304.         return true;
  305.       }
  306.     }
  307.  
  308.     return false;
  309.   }
  310.  
  311.   // added by chains 09/29/2000 (petertay)
  312.   // should the param be included or filtered out
  313.   function QualifiesForActiveIFace(oElem, sCurLang)
  314.   {
  315.     var sRIDs = oElem.getAttribute("rids");
  316.     if (!sRIDs)
  317.     {
  318.       return true;
  319.     }
  320.  
  321.     if (sCurLang != 'cpp')
  322.     {
  323.       return true;
  324.     }
  325.  
  326.     var oActiveIFace = GetActiveIFace();
  327.     if (!oActiveIFace)
  328.     {
  329.       return true;
  330.     }
  331.  
  332.     var sActiveRID = oActiveIFace.getAttribute("rid");
  333.     if (!sActiveRID)
  334.     {
  335.       // Yikes! DTD should NEVER allow this to occur
  336.       return true;
  337.     }
  338.  
  339.     var oRegInList = new RegExp("\\b" + sActiveRID + "\\b");
  340.  
  341.     if (oRegInList.test(sRIDs))
  342.     {
  343.       return true;
  344.     }
  345.  
  346.     return false;
  347.  
  348.   }
  349.  
  350.  
  351.   // If the type start with a vowel or an H, the data type is soft
  352.   // sounds and should be preceded by "an" rather than "a".
  353.   function IsSoftSounding(sType)
  354.   {
  355.     if (!sType)
  356.     {
  357.       return false;
  358.     }
  359.     var oReg = /^[AaEeIiOoUuH]/;
  360.     return (oReg.test(sType) ? true : false);
  361.   }
  362.  
  363.   // This is only a poor guess that the param represented by o describes an interface
  364.   function IsIFace(o)
  365.   {
  366.     var sType = o.getAttribute('type');
  367.     if (!sType)
  368.     {
  369.       return false;
  370.     }
  371.  
  372.     if (sType.substring(0,1) == "I" && o.getAttribute('pointerlevel') >= 1)
  373.     {
  374.       return true;
  375.     }
  376.     else
  377.     {
  378.       return false;
  379.     }
  380.   }
  381.  
  382.   // Return a portion of the path using the specified mask
  383.   // iPortion values:
  384.   //  0 == text before the mask,
  385.   //  1 == text following the mask,
  386.   //  2 == text before and including the mask,
  387.   //  3 == text after and including the mask
  388.   // if the mask cannot be found within the path, the entire path is returned
  389.   function PartialPathOf(sPath, sMask, iPortion)
  390.   {
  391.     if (typeof(iPortion) == 'undefined')
  392.     {
  393.       return sPath;
  394.     }
  395.   //normalize the path. The document path when loaded from IE uses "/". But when loaded from script it uses "\".
  396.   while (sPath.indexOf("\\")!=-1)
  397.   {
  398.     sPath=sPath.replace("\\","/");
  399.   }
  400.  
  401.     var oReg = new RegExp("(.*)" + sMask + "(.*)", "i");
  402.     if (oReg.test(sPath))
  403.     {
  404.       switch(iPortion)
  405.       {
  406.       case 0:
  407.         return RegExp.$1;
  408.       case 1:
  409.         return RegExp.$2;
  410.       case 2:
  411.         return RegExp.$1 + sMask;
  412.       case 3:
  413.         return sMask + RegExp.$2;
  414.       }
  415.     }
  416.     else
  417.     {
  418.       return sPath;
  419.     }
  420.   }
  421.  
  422.   // replicate the specified string (sRepl) iTimes times.
  423.   function ReplStr(sRepl, iTimes)
  424.   {
  425.     var sOut = "";
  426.     for (var i = 0; i < iTimes; i++)
  427.     {
  428.       sOut+=sRepl;
  429.     }
  430.     return sOut;
  431.   }
  432.  
  433.   // Given an associative array, convert it to a string where each item is separated by the specified delimeter
  434.   function StringFromHash(aHash, sDelim)
  435.   {
  436.     var s = "";
  437.     for (sItem in aHash)
  438.     {
  439.       s += sItem + sDelim;
  440.     }
  441.  
  442.     var oReg = new RegExp(sDelim + "$");
  443.     s = s.replace(oReg, ""); // lop off trailing comma
  444.     return s;
  445.   }
  446.  
  447.   // Collect the conceptual index entries from the doc.
  448.   // Indexer expects to find these as an IDX_CONCEPT expando on the top-level H1.
  449.   // Web Crawlers expect to find these in the Keywords META.
  450.   // HTMLHelp expects to find these in MS-HKWD METAs.
  451.   function GatherConcepts(o, sDelim)
  452.   {
  453.     var aConcepts = {};
  454.     var oDoc = o.ownerDocument;
  455.  
  456.     var sIndexQuery = "/inetsdk:topic/metadata/index";
  457.     var oIndex = oDoc.selectSingleNode(sIndexQuery);
  458.     var bNoDefIndex = false;
  459.     if (oIndex)
  460.     {
  461.       if (oIndex.getAttribute("noindex"))
  462.       {
  463.         bNoDefIndex = true;
  464.       }
  465.  
  466.       var oKeyWords = oIndex.selectNodes("kw");
  467.       for (var iKW = 0; iKW < oKeyWords.length; iKW++)
  468.       {
  469.         aConcepts[oKeyWords[iKW].text.toLowerCase()] = "1";
  470.       }
  471.     }
  472.  
  473.     // delimeter specification indicates that the output is for IDX_CONCEPT
  474.     // since indexer will index the topic name, don't repeat it in the concept list
  475.     if (!bNoDefIndex && !sDelim)
  476.     {
  477.       var sNameQuery = "/inetsdk:topic/metadata/@name";
  478.       var oName = oDoc.selectSingleNode(sNameQuery);
  479.       if (oName)
  480.       {
  481.         aConcepts[oName.value] = "1";
  482.       }
  483.     }
  484.  
  485.     if (sDelim)
  486.     {
  487.       return StringFromHash(aConcepts, sDelim);
  488.     }
  489.     else
  490.     {
  491.       return aConcepts;
  492.     }
  493.   }
  494.  
  495.   // Collect keywords from the document and spit them out as <META KEYWORDS.../>
  496.   // This code recognizes <kw> tags and <tla> and <term> tags with a kw attribute
  497.   // Consider supporting <xref> with a kw attribute.
  498.   // avoid dupes by converting all keywords to lowercase and by storing them in a hash table
  499.   function GatherKeywords(o, sDelim)
  500.   {
  501.     var oDoc = o.ownerDocument;
  502.  
  503.     if (!sDelim)
  504.     {
  505.       sDelim = ",";
  506.     }
  507.  
  508.     // don't pass a delimeter because we want to get back a hash table
  509.     var aKeywords = GatherConcepts(o);
  510.  
  511.     var sQuery = "/inetsdk:topic/content//kw";
  512.     var oNodes = oDoc.selectNodes(sQuery);
  513.     var i;
  514.     for (i = 0; i < oNodes.length; i++)
  515.     {
  516.       var oNode = oNodes[i];
  517.       aKeywords[oNode.text.toLowerCase()] = "1";
  518.     }
  519.  
  520.     sQuery = "/inetsdk:topic/content//tla[@kw]";
  521.     oNodes = oDoc.selectNodes(sQuery);
  522.     for (i = 0; i < oNodes.length; i++)
  523.     {
  524.       //at: Search the central pre-loaded acronyms.xml DOM.
  525.       var sRid = oNodes[i].getAttribute("rid");
  526.       var oAc = goLookup.RetrieveAcronym(sRid);
  527.       if (oAc)
  528.       {
  529.         var oNode = oAc.selectSingleNode("primary");
  530.         if (oNode)
  531.           aKeywords[oNode.text.toLowerCase()] = "1";
  532.       }
  533.     }
  534.  
  535.     sQuery = "/inetsdk:topic/content//term[@kw]";
  536.     oNodes = oDoc.selectNodes(sQuery);
  537.     for (i = 0; i < oNodes.length; i++)
  538.     {
  539.       var oNode = oDoc.selectSingleNode("/inetsdk:topic/inetsdk:glossary/gloss_entry[@id = '" + oNodes[i].getAttribute("rid") + "']/@name");
  540.       if (oNode)
  541.       {
  542.         aKeywords[oNode.text.toLowerCase()] = "1";
  543.       }
  544.     }
  545.  
  546.     return StringFromHash(aKeywords, sDelim);
  547.   }
  548.  
  549.   var gSpecialContainer = {"seealso" : 1, "applies" : 1, "related_topics" : 1};
  550.   function IsPrivilegedLink(o)
  551.   {
  552.     //return (gSpecialContainer[o.parentNode.nodeName] != null ? true : false);
  553.  
  554.     // need to walk the parent chain since links can be embedded inside if/sw and other markup
  555.     // rather than directly inside a special container
  556.     var oParent = o;
  557.     while (oParent = oParent.parentNode)
  558.     {
  559.       if (gSpecialContainer[oParent.nodeName] != null)
  560.       {
  561.         return true;
  562.       }
  563.     }
  564.     return false;
  565.   }
  566.  
  567.   // determine whether or not this link should be enabled
  568.   // rule: must be the first instance or must be explicitly enabled
  569.   function ShouldLink(oSrc, oCtx)
  570.   {
  571.     return (oSrc.getAttribute("enabled") || IsPrivilegedLink(oSrc) || IsFirstLink(oSrc, oCtx) ? true : false);
  572.   }
  573.  
  574.   // determine whether or not the node should be glossarized
  575.   // rule: must be the first instance or must be explicitly enabled
  576.  
  577.   // keep tabs on glossary references. This is a more memory intensive but
  578.   // less processing intensive (fewer DOM query/traverses), and more
  579.   // reliable since a gloss entry may be referenced earlier in the tree but for a
  580.   // different dev language
  581.  
  582.   function ShouldGlossarize(o)
  583.   {
  584.     var sID = o.getAttribute("rid");
  585.     if (!sID) return false;
  586.  
  587.     if (typeof(ShouldGlossarize._table) == 'undefined')
  588.     {
  589.       ShouldGlossarize._table = new Array();
  590.       ShouldGlossarize._table[sID] = 1;
  591.       return true;
  592.     }
  593.  
  594.     if (!ShouldGlossarize._table[sID])
  595.     {
  596.       ShouldGlossarize._table[sID] = 1;
  597.       return true;
  598.     }
  599.  
  600.     if (o.getAttribute("enabled"))
  601.     {
  602.       return true;
  603.     }
  604.  
  605.     return false;
  606.   }
  607.  
  608.  
  609.   // determine if the link (o) is the first occurrence of a
  610.   // cross-reference to the topic with the specified @rid
  611.   // BUGBUG: Check for type="pn", and concatenate that onto the key
  612.   function IsFirstLink(o, oCtx)
  613.   {
  614.     var sID = o.getAttribute("rid");
  615.     if (!sID) return false;
  616.  
  617.     var sFid = o.getAttribute("fid"); // #fragment-id
  618.     var sIid = o.getAttribute("iid"); // #interface-id
  619.     var sCid = o.getAttribute("cid"); // #constant-id
  620.  
  621.     // use the devlang on the source tag before the global devlang
  622.     var sDevLang = o.getAttribute("devlang");
  623.     if (!sDevLang)
  624.     {
  625.       sDevLang = oCtx._devlang;
  626.     }
  627.  
  628.     // differentiate between persistent and runtime requests
  629.     var sType = o.getAttribute("type");
  630.  
  631.     var sKey = sID +
  632.       (typeof(sDevLang) != 'undefined' ? sDevLang : '') +
  633.       (sFid != null ? sFid : '') +
  634.       (sIid != null ? sIid : '') +
  635.       (sCid != null ? sCid : '') +
  636.       (sType != null ? sType : '');
  637.  
  638.     if (typeof(IsFirstLink._linkTable) == 'undefined')
  639.     {
  640.       IsFirstLink._linkTable = new Array();
  641.       IsFirstLink._linkTable[sKey] = 1;
  642.       return true;
  643.     }
  644.  
  645.     if (!IsFirstLink._linkTable[sKey])
  646.     {
  647.       IsFirstLink._linkTable[sKey] = 1;
  648.       return true;
  649.     }
  650.  
  651.     return false;
  652.  
  653.   }
  654.  
  655.   // In the current document, is this node the first of its type (term)
  656.   // using this node's rid.
  657.   // JK: This is the origianl IsFirst definition.
  658.   // This is a temporary workaround until glossary becomes part of lookup.
  659.   function IsFirstTerm(o)
  660.   {
  661.     var oTestNode;
  662.     var sID = o.getAttribute("rid");
  663.     if (!sID) return false;
  664.     var oNestedVersions = o.ownerDocument.selectNodes("/inetsdk:topic/inetsdk:acronyms/acronym[./primary/tla/@rid = '" + sID + "']");
  665.     var oThisNode;
  666.     // find the first node in the document that uses this id.
  667.     var oNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + sID + "']");
  668.  
  669.     if (!oNode)
  670.     {
  671.       switch(o.parentNode.nodeName)
  672.       {
  673.         case "primary":
  674.         {
  675.           //need to check if there is another node that shares this tla...
  676.         if(oNestedVersions.length>0)
  677.         {
  678.           oThisNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + o.parentNode.parentNode.getAttribute("id") + "']");
  679.           if(oThisNode)
  680.           {
  681.               for(i=0;i<oNestedVersions.length;i++)
  682.               {
  683.                 oTestNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + oNestedVersions[i].getAttribute("id") + "']");
  684.                 if (oTestNode)
  685.                 {
  686.                   if (uniqueID(oTestNode) < uniqueID(oThisNode))
  687.                   {
  688.                     return false;
  689.                   }
  690.                 }
  691.               }
  692.  
  693.               return true;
  694.             }
  695.             else
  696.             {
  697.               return true;
  698.             }
  699.         }
  700.         else
  701.         {
  702.           return true;
  703.         }
  704.  
  705.         break;
  706.  
  707.         }
  708.         case "secondary":
  709.         {
  710.           return false;
  711.         break;
  712.         }
  713.         default:
  714.         {
  715.         }
  716.  
  717.       }
  718.     return true;
  719.     }
  720.   else
  721.     {
  722.     switch(o.parentNode.nodeName)
  723.     {
  724.       case "secondary":
  725.       {
  726.         return false;
  727.         break;
  728.       }
  729.       case "primary":
  730.       {
  731.         oThisNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + o.parentNode.parentNode.getAttribute("id") + "']");
  732.         if(oThisNode)
  733.         {
  734.           if (uniqueID(oNode) < uniqueID(oThisNode))
  735.           {
  736.             return false;
  737.           }
  738.  
  739.             if (oNestedVersions.length>0)
  740.             {
  741.               for(i=0;i<oNestedVersions.length;i++)
  742.               {
  743.                 oTestNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + oNestedVersions[i].getAttribute("id") + "']");
  744.                 if (oTestNode)
  745.                 {
  746.                   if (uniqueID(oTestNode) < uniqueID(oThisNode))
  747.                   {
  748.                     return false;
  749.                   }
  750.                 }
  751.               }
  752.  
  753.               return true;
  754.             }
  755.             else
  756.             {
  757.               return true;
  758.             }
  759.           }
  760.           else
  761.           {
  762.             return true;
  763.           }
  764.       }
  765.       default:
  766.       {
  767.         //this should be the case where there it isn't a nested tla...
  768.         break;
  769.       }
  770.     }
  771.   }
  772.  
  773.     if (uniqueID(oNode) == uniqueID(o))
  774.     {
  775.       if (oNestedVersions.length>0)
  776.       {
  777.         for(i=0;i<oNestedVersions.length;i++)
  778.         {
  779.           oTestNode = o.ownerDocument.selectSingleNode("inetsdk:topic/content//" + o.nodeName + "[@rid='" + oNestedVersions[i].getAttribute("id") + "']");
  780.           if (oTestNode)
  781.           {
  782.             if (uniqueID(oTestNode) < uniqueID(oNode))
  783.             {
  784.               return false;
  785.             }
  786.           }
  787.         }
  788.  
  789.         return true;
  790.       }
  791.       else
  792.       {
  793.         return true;
  794.       }
  795.     }
  796.     else
  797.     {
  798.       if(o.parentNode.nodeName=="primary")
  799.       {
  800.         return true;
  801.       }
  802.       else
  803.       {
  804.         return false;
  805.       }
  806.     }
  807.   }
  808.  
  809.  
  810.   // Change the file extension of the path. If the extension is empty,
  811.   // do nothing
  812.   function ChangeExt(sPath, sExt)
  813.   {
  814.     if (!sExt || /^$/.test(sExt))
  815.     {
  816.       return sPath;
  817.     }
  818.  
  819.     if (!/^\./.test(sExt))
  820.     {
  821.       sExt = "." + sExt;
  822.     }
  823.  
  824.     return sPath.substring(0, sPath.lastIndexOf(".")) + sExt;
  825.   }
  826.  
  827.   // Given d:\foo\bar\goo.htm, return "htm"
  828.   function JustExt(sPath)
  829.   {
  830.     var iPos = sPath.lastIndexOf(".");
  831.     if (iPos >= 0 && sPath.length > iPos+1)
  832.     {
  833.       return sPath.substring(iPos+1);
  834.     }
  835.     else
  836.     {
  837.       return "";
  838.     }
  839.   }
  840.  
  841.   // Given d:\foo\bar\goo.htm, return "goo.htm"
  842.   function JustFName(sPath)
  843.   {
  844.     sPath =  sPath.replace(/[\\\\]/g, "/"); // convert backslashes to forward slashes
  845.     var aParts = sPath.split("/"); // split on forward slash
  846.     return aParts[aParts.length-1];
  847.   }
  848.  
  849.   // Given d:\foo\bar\goo.htm, return "d:\foo\bar"; slashes a reversed
  850.   function JustPath(sPath)
  851.   {
  852.     sPath =  sPath.replace(/[\\\\]/g, "/"); // convert backslashes to forward slashes
  853.     var aParts = sPath.split("/"); // split on forward slash
  854.     aParts.length -= 1;
  855.     return (aParts.length == 0 ? "." : aParts.join("/"));
  856.   }
  857.  
  858.   // Given d:\foo\bar\goo.htm, return "goo"
  859.   function JustStem(sPath)
  860.   {
  861.     var sFile = JustFName(sPath);
  862.     var aParts = sFile.split(".");
  863.     aParts.length -= 1;
  864.     return aParts.join(".");
  865.   }
  866.  
  867.  
  868.   // dependency: observe the explicit XQL query
  869.   function GetPublishedPathOfTopic()
  870.   {
  871.     if (typeof(GetPublishedPathOfTopic.pubpath) == 'string')
  872.     {
  873.       return GetPublishedPathOfTopic.pubpath;
  874.     }
  875.  
  876.     var oPubPath = ownerDocument.selectSingleNode("/HTML/HEAD/ph:header/ph:data/XML[@ID='_topicdata']/@pubpath");
  877.     if (oPubPath)
  878.     {
  879.       return (GetPublishedPathOfTopic.pubpath = oPubPath.value);
  880.     }
  881.     else
  882.     {
  883.       return null;
  884.     }
  885.   }
  886.  
  887.   // wraps the GeneratePath call because returning null to an xsl:eval is fatal
  888.   function GeneratePathWrapper(sPubPath, sDestPath, sMedia)
  889.   {
  890.     var sFinalPath = GeneratePath(sPubPath, sDestPath, sMedia);
  891.     if (typeof(sFinalPath) == 'string')
  892.     {
  893.       return sFinalPath;
  894.     }
  895.     else
  896.     {
  897.       return "";
  898.     }
  899.   }
  900.  
  901.   //  Build a path relative to the published location of the current
  902.   //  topic if the media is 'chm' or 'HXS'.
  903.   //  Otherwise return the path unchanged.
  904.   function GeneratePath(sPubPath, sDestPath, sMedia)
  905.   {
  906.     if (typeof(sMedia) != 'string' || (sMedia != 'chm' && sMedia != 'hxs'))
  907.     {
  908.       return sDestPath;
  909.     }
  910.  
  911.     if (!sPubPath)
  912.     {
  913.       // BUGBUG: Cache the error somewhere
  914.       //oDest.error = "published path unavailable";
  915.       return null;
  916.     }
  917.  
  918.     var sHREF;
  919.     // BUGBUG: htm extension is hard-coded in the CHM case.
  920.     sHREF = MakeRelative(sPubPath, sDestPath);
  921.     if (!sHREF)
  922.     {
  923.       // BUGBUG: Cache the error somewhere
  924.       //oDest.error = "VROOT2Relative failure.";
  925.       return null;
  926.     }
  927.     else
  928.     {
  929.       // extension map. Only change the target path if its extension is in the map.
  930.       // BUGBUG: Hardcoded...
  931.       var aExt = {'asp' : 'htm'};
  932.       var sExt = JustExt(sHREF);
  933.       if (sExt)
  934.       {
  935.         var sNewExt = aExt[sExt];
  936.         if (sNewExt)
  937.         {
  938.           sHREF = ChangeExt(sHREF, sNewExt);
  939.         }
  940.       }
  941.       return sHREF;
  942.     }
  943.  
  944.   }
  945.  
  946.   // Compose a path to the specified destination path relative to the specified container path
  947.   // The composition is performed case insensitively
  948.   function MakeRelative(sContainer, sDestPath)
  949.   {
  950.     // c:/sitebuilder/workshop/author/dhtml/reference/properties.htm
  951.     //   /sitebuilder/shared/css/ie4-wks.css
  952.     //   ../../../../shared/css/ie4-wks.css
  953.  
  954.     // c:/sitebuilder/workshop/author/dhtml/reference/properties.htm
  955.     //               /workshop/author/dhtml/reference/properties/accessKey.htm
  956.     //                                                properties/accessKey.htm
  957.  
  958.     // c:/sitebuilder/workshop/author/dhtml/reference/properties.htm
  959.     //               /workshop/code/common.js
  960.     //               ../../../code/common.js
  961.  
  962.     // path is already relative
  963.     if (/^\.\./.test(sDestPath))
  964.     {
  965.       return sDestPath;
  966.     }
  967.  
  968.     // normalize the paths
  969.     var oRegBS = /\\/g;
  970.     sContainer = sContainer.replace(oRegBS, "/");
  971.     sDestPath = sDestPath.replace(oRegBS, "/");
  972.  
  973.     if (/^http:\/\//.test(sDestPath))
  974.     {
  975.       return sDestPath;
  976.     }
  977.  
  978.     // BUGBUG: make sure topics are on the same drive/protocol/server
  979.     var oRegNoProtocol = /^(file:\/\/\/)?([a-zA-z]):/;
  980.     sContainer = sContainer.replace(oRegNoProtocol, "");
  981.     sDestPath = sDestPath.replace(oRegNoProtocol, "");
  982.  
  983.     sDestPath = sDestPath.replace(/^\//, ""); // lop leading slash to eliminate empty first array element after split
  984.  
  985.     var aSrc = sContainer.split(/\//);
  986.     aSrc.length -= 1; // lop off the filename from the container (assume container is a reference to a file)
  987.  
  988.     var bTrailingSlash = (/\/$/.test(sDestPath)); // preserve trailing slash
  989.     var aDest = sDestPath.split(/\//);
  990.  
  991.     var iSrcLen = aSrc.length, iDestLen = aDest.length;
  992.     var iSrcIndex = 0, iDestIndex = 0, iNoMatch = 0;
  993.  
  994.     // walk forward looking for matching portion of path
  995.     var bMatched = 0;
  996.     for (iSrcIndex = 0; iSrcIndex < iSrcLen; iSrcIndex++)
  997.     {
  998.       if (aSrc[iSrcIndex].toLowerCase() != aDest[iDestIndex].toLowerCase())
  999.       {
  1000.         iNoMatch++;
  1001.       }
  1002.       else
  1003.       {
  1004.         bMatched =  1;
  1005.         break;
  1006.       }
  1007.     }
  1008.  
  1009.     if (bMatched)
  1010.     {
  1011.  
  1012.       var aRelPath = new Array();
  1013.  
  1014.       while (iSrcIndex < iSrcLen && iDestIndex < iDestLen && aSrc[iSrcIndex].toLowerCase() == aDest[iDestIndex].toLowerCase())
  1015.       {
  1016.         iSrcIndex++; iDestIndex++;
  1017.       }
  1018.  
  1019.       // tack remaining portion of destination path onto the end of the result
  1020.       while (iDestIndex < iDestLen)
  1021.       {
  1022.         aRelPath[aRelPath.length] = aDest[iDestIndex];
  1023.         iDestIndex++;
  1024.       }
  1025.  
  1026.       var sRelPath = aRelPath.join('/');
  1027.  
  1028.       // climb out of what remains of the source (excluding the filename)
  1029.       while (iSrcIndex < iSrcLen)
  1030.       {
  1031.         sRelPath = "../" + sRelPath;
  1032.         iSrcIndex++;
  1033.       }
  1034.  
  1035.       return sRelPath + (bTrailingSlash ? "/" : "");
  1036.     }
  1037.     else // BUGBUG: no overlap, so just return what was passed in?
  1038.     {
  1039.       return sDestPath;
  1040.     }
  1041.   }
  1042.  
  1043.   // return the string s with the first letter capitalized
  1044.   function Proper(s)
  1045.   {
  1046.     return (/^(.)(.*)/.test(s) ? RegExp.$1.toUpperCase() + RegExp.$2 : s);
  1047.   }
  1048.  
  1049.   // return the proper string associated with the supplied page type
  1050.   function ProperPageType(s)
  1051.   {
  1052.     switch ( s )
  1053.   {
  1054.   case "attribute":
  1055.   case "behavior":
  1056.   case "collection":
  1057.   case "constants":
  1058.   case "event":
  1059.   case "function":
  1060.   case "method":
  1061.   case "object":
  1062.   case "property":
  1063.   case "rule":
  1064.     return Proper( s );
  1065.   case "dhcmdid":
  1066.     return "Command Identifier";
  1067.   case "dhfilter":
  1068.     return "Filter";
  1069.   case "dhfilter_method":
  1070.     return "Method";
  1071.   case "dhfilter_property":
  1072.     return "Property";
  1073.   case "enum":
  1074.     return "Enumerated Type";
  1075.   case "howto":
  1076.     return "Tutorial";
  1077.   case "iface":
  1078.     return "Interface";
  1079.   case "ovw":
  1080.     return "Overview";
  1081.   case "pseudo_element":
  1082.     return "Pseudo-element";
  1083.   case "struct":
  1084.     return "Structure";
  1085.     default:
  1086.     return "";
  1087.   }
  1088.   }
  1089.  
  1090.   // chains 5-04-01
  1091.   // Used by glossary_page.xsl and alphabetic_link.xsl
  1092.   // Checks a gloss_entry node or nodeSet to see if any nodes contain all the filters defined for a page
  1093.   function CheckFilters(aGlossaryNodeOrNodes, bIsNodeSet)
  1094.   {
  1095.     var aPageTechs = this.selectNodes("//inetsdk:topic/metadata/tech");
  1096.     var aTechStrings = new Array();
  1097.     for (i = 0; i < aPageTechs.length; i++)
  1098.     {
  1099.         aTechStrings[i] = aPageTechs[i].getAttribute("value");
  1100.     }
  1101.     
  1102.     if (bIsNodeSet == false)
  1103.     {
  1104.         // aGlossaryNodeOrNodes is a single node
  1105.         aNodeTechs = aGlossaryNodeOrNodes.selectNodes("tech");
  1106.         if (aNodeTechs.length == 0) return true; // default is to include
  1107.         iNumberFound = 0;
  1108.         
  1109.         for (j = 0; j < aNodeTechs.length; j++)
  1110.         {
  1111.             for (k = 0; k < aTechStrings.length; k++)
  1112.             {
  1113.                 if (aTechStrings[k] == aNodeTechs[j].getAttribute("value"))
  1114.                     iNumberFound++                    
  1115.             }
  1116.         }
  1117.         
  1118.         if (iNumberFound == aTechStrings.length) return true;
  1119.     }
  1120.     else
  1121.     {
  1122.         // for each node, check to see if all page techs are present
  1123.         // if so, set bFound to true  
  1124.         for (i = 0; i < aGlossaryNodeOrNodes.length; i++)
  1125.         {
  1126.             oNode = aGlossaryNodeOrNodes[i];
  1127.             aNodeTechs = oNode.selectNodes("tech");
  1128.             if (aNodeTechs.length == 0) return true; // default is to include
  1129.             iNumberFound = 0;
  1130.             
  1131.             for (j = 0; j < aNodeTechs.length; j++)
  1132.             {
  1133.                 for (k = 0; k < aTechStrings.length; k++)
  1134.                 {
  1135.                     if (aTechStrings[k] == aNodeTechs[j].getAttribute("value"))
  1136.                         iNumberFound++                    
  1137.                 }
  1138.             }
  1139.             
  1140.             if (iNumberFound == aTechStrings.length) return true;
  1141.         }
  1142.     }
  1143.     
  1144.     return false;
  1145.   }
  1146.  
  1147.   // chains 6-8-01
  1148.   // Used by utopia-wks.xsl
  1149.   // Creates string for @content in META @description
  1150.   // Converts quotes and apostrophies to entities
  1151.   // Removes line breaks and tabs.
  1152.   // This function is necessary for Utopia because the META description 
  1153.   // becomes a jscript object property in the utopia-wks.xsl transform
  1154.   // BUGBUG: currently loses text for xref and tla nodes in oNode 
  1155.   // It should apply a stylesheet to oNode that converts these nodes to text
  1156.   function FormatNodeForMETA(oNode, sXSL)
  1157.   {
  1158.     var sText = "";
  1159.     if (!oNode) return sText;
  1160.     sText = oNode.text;
  1161.  
  1162.     var i = 0;
  1163.     while ((i = sText.indexOf("\"")) != -1)
  1164.     {
  1165.         sText = sText.substring(0, i) + """ + sText.substring(i + 1);
  1166.     }
  1167.     
  1168.     //var i = 0;
  1169.     while ((i = sText.indexOf("\'")) != -1)
  1170.     {
  1171.         sText = sText.substring(0, i) + "'" + sText.substring(i + 1);
  1172.     }
  1173.  
  1174.     //var i = 0;
  1175.     while ((i = sText.indexOf("\n")) != -1)
  1176.     {
  1177.         sText = sText.substring(0, i) + sText.substring(i + 1);
  1178.     }
  1179.  
  1180.     //var i = 0;
  1181.     while ((i = sText.indexOf("\r")) != -1)
  1182.     {
  1183.         sText = sText.substring(0, i) + sText.substring(i + 1);
  1184.     }
  1185.  
  1186.     //var i = 0;
  1187.     while ((i = sText.indexOf("\t")) != -1)
  1188.     {
  1189.         sText = sText.substring(0, i) + sText.substring(i + 1);
  1190.     }
  1191.  
  1192.     return sText;
  1193.   }
  1194.   
  1195. // chains 6-19-01
  1196. // Used by scr_property.xsl
  1197. // Helps page determine whether property belongs to an HTML element 
  1198. // and should use a syntax section that includes HTML syntax
  1199. function DoesObjectHavePN()
  1200. {
  1201.     var oObjectNodes;
  1202.     var oTNode;
  1203.     var sRid = "";
  1204.     var sPN = "";
  1205.  
  1206.     oObjectNodes = this.selectNodes("//metadata/applies/object");
  1207.     
  1208.     for (i = 0; i < oObjectNodes.length; i++)
  1209.     {
  1210.         sRid = oObjectNodes(i).getAttribute("rid");
  1211.         oTNode = goLookup.RetrieveTarget(sRid);
  1212.         if (!oTNode) continue;
  1213.         else sPN = oTNode.getAttribute("pn")
  1214.         if (sPN && sPN != "") return true;
  1215.     }
  1216.     
  1217.     return false;
  1218. }
  1219.  
  1220. // chains 6-20-01
  1221. // Used by scr_property.xsl
  1222. // Helps page determine whether property belongs to an HTML element 
  1223. // and should use a syntax section that includes HTML syntax
  1224. function ObjectTypeEquals(sType)
  1225. {
  1226.     var oObjectNodes;
  1227.     var oTNode;
  1228.     var sRid = "";
  1229.     var sObjectType = "";
  1230.  
  1231.     oObjectNodes = this.selectNodes("//metadata/applies/object");
  1232.     
  1233.     for (i = 0; i < oObjectNodes.length; i++)
  1234.     {
  1235.         sRid = oObjectNodes(i).getAttribute("rid");
  1236.         oTNode = goLookup.RetrieveTarget(sRid);
  1237.         if (!oTNode) continue;
  1238.         else sObjectType = oTNode.getAttribute("type")
  1239.         if (sObjectType && sObjectType == sType) return true;
  1240.     }
  1241.     
  1242.     return false;
  1243. }
  1244.  
  1245. // chains 6-26-01: Used by utopia-wks.xsl
  1246. // Script inserted into Utopia template via sHeaderString must have additional back slashes in
  1247. // line breaks and quotes for proper escape character sequence
  1248. function FormatForUtopiaHeaderString(oNode, sProjRoot)
  1249. {
  1250.     var sText = "";
  1251.     if (!oNode) return sText;
  1252.  
  1253.     var sTestString = "/production/xml/";
  1254.     var sReplacementText = sProjRoot + "/";
  1255.     var oRegExp = new RegExp(sTestString, "g");
  1256.  
  1257.     sText = oNode.xml;
  1258.  
  1259.     if (sText.indexOf(sTestString) != -1) 
  1260.         sText = sText.replace(oRegExp, sReplacementText);
  1261.  
  1262.     var i = 0;
  1263.     while ((i = sText.indexOf("\n", i)) != -1)
  1264.     {
  1265.         sText = sText.substring(0, i - 1) + "\\n" + sText.substring(i + 1);
  1266.     }
  1267.  
  1268.     var i = 0;
  1269.     while ((i = sText.indexOf("\"", i + 2)) != -1)
  1270.     {
  1271.         sText = sText.substring(0, i) + "\\\"" + sText.substring(i + 1);
  1272.     }
  1273.  
  1274.     return sText;
  1275. }
  1276.  
  1277. // chains 6-26-01
  1278. // Used by utopia-wks.xsl
  1279. // Gets the name of a file from an @HREF attribute that specifies a path to a script or css file
  1280. function GetFileName(oNode)
  1281. {
  1282.     var sFileName = "";
  1283.     if (!oNode) return sFileName;
  1284.     
  1285.     sFullName = oNode.nodeValue;
  1286.     if (sFullName == "") return sFileName;
  1287.  
  1288.     var iLastSlash = sFullName.lastIndexOf("/");
  1289.     if (iLastSlash == -1) iLastSlash = sFullName.lastIndexOf("\\");
  1290.     if (iLastSlash == -1) return sFileName;
  1291.     else return sFullName.substring(iLastSlash + 1);
  1292. }
  1293.  
  1294. function  BuildObjectList()
  1295. {
  1296. //debugger;
  1297.     var sRet = "";
  1298.     var oXMLDoc = this.ownerDocument;
  1299.     var sName = oXMLDoc.selectSingleNode("//metadata/@name").value;
  1300.     var sCriteria = "[dlang/@value='" + goLookup._oCtx._devlang + "']";
  1301.     //if (!NeedsDisambiguation(sName, goDest, sCriteria))
  1302.     //    return sRet;
  1303.     // Check with lookupbyName type thing for multiple pages with same metadata/@name
  1304.     
  1305.     // construct string from applies/object (or applies/iface too?)
  1306.     var oAppliesNode = oXMLDoc.selectSingleNode("//applies");
  1307.     if (!oAppliesNode) return sRet;
  1308.     var oObjectNodes = oAppliesNode.selectNodes("object");
  1309.     sRet = " (";
  1310.     for (i = 0; (i < 3) && i < (oObjectNodes.length); i++)
  1311.     {
  1312.         sObjectRid = oObjectNodes[i].getAttribute("rid");
  1313.         // lookup in targets and get name
  1314.         goLookup.LookupByRID(sObjectRid, goDest);
  1315.         sObjectName = goDest.GetPersistentName();
  1316.         if (sObjectName == "" || sObjectName == undefined) sObjectName = goDest.GetCaption();
  1317.         //if (sObjectName == "") sObjectName = oObjTarg.GetAttribute("name");
  1318.         
  1319.         sRet = sRet + sObjectName;
  1320.         if (i + 1 < oObjectNodes.length && i < 2) sRet = sRet + ", ";
  1321.     }
  1322.     if (oObjectNodes.length > 3) sRet = sRet + ", ...";
  1323.     sRet = sRet + ")";
  1324.     return sRet;
  1325. }
  1326.  
  1327. /*
  1328. function NeedsDisambiguation(sName, oDest, sCriteria)
  1329. {
  1330.   var bRet = false;
  1331.   
  1332.   
  1333.   var bOk = false;
  1334.   var sTargXML = null;
  1335.   var sTPath = goLookup._oCtx._sDrive + goLookup._oCtx.GetPathOf("targets");
  1336.   var oTNodes = null;
  1337.   var oTNode = null;
  1338.   var oData = null;
  1339.   var bLuCache = goLookup._oCtx.CacheLookups();
  1340.  
  1341.   oData = goLookup.EnsureData(bLuCache);
  1342.   bLuCache = goLookup._oCtx.CacheLookups();
  1343.  
  1344.   oDest.Init();
  1345.  
  1346.   if (sName)
  1347.   {
  1348.     oDest.SetCaption(sName);
  1349.  
  1350.     sCriteria = NormalizeCriteria(sCriteria);
  1351.  
  1352.     if (bLuCache && oData)
  1353.     {
  1354.       // Try to use the LuCache Lookup Cache.
  1355.       try
  1356.       {
  1357.         // Call LuCache to lookup the name and get back the node-xml.
  1358.         sTargXML = oData.LookupField(sName, "name", sTPath, sCriteria);
  1359.       }
  1360.       catch(e)
  1361.       {
  1362.         sTargXML = null;
  1363.       }
  1364.       if (sTargXML)
  1365.       {
  1366.         var oTDom = goLookup._oCtx._oTDom;
  1367.  
  1368.         // Now use mini-dom node to load node-xml and get a node.
  1369.         oTDom.async = false;
  1370.         oTDom.loadXML(sTargXML);
  1371.         oTNode = oTDom.documentElement;
  1372.         if (oTNode)
  1373.           bOk = true;
  1374.         else
  1375.           goLookup._error = "cannot load node xml.";
  1376.       }
  1377.       else
  1378.         goLookup._error = "cannot locate " + sName;
  1379.     }
  1380.     else
  1381.     {
  1382.       // Try to use a loaded DOM for lookups.
  1383.       if (bLuCache && !oData)
  1384.         oData = goLookup.EnsureData(false);
  1385.       if (oData)
  1386.       {
  1387.         oTNodes = oData.selectNodes("/inetsdk:targets/targ[@name='" + sName + "']" + sCriteria);
  1388.         //oTNodes = oTNodes.selectNodes("dlang[@value='" + sCriteria + "']");
  1389.         if (oTNodes.length > 1) bRet = true;
  1390.       }
  1391.       else
  1392.         goLookup._error = "cannot create access to targets.";
  1393.     }
  1394.   }
  1395.  
  1396.   return bRet;
  1397. }
  1398. */
  1399.  
  1400. function NeedsNewGif()
  1401. {
  1402.     //return true;
  1403.     sXml = this.xml;
  1404.     if (sXml.indexOf("new.gif") != -1) return true;
  1405.     else return false;
  1406. }
  1407.  
  1408.   /********************
  1409.   * unused code below *
  1410.   *********************/
  1411.  
  1412.   // force see also links to be enabled
  1413.   //BUGBUG: Can't modify a read-only node.
  1414.   //BUGBUG: By design the XML document is read-only during transformation.
  1415.   /*
  1416.   function TweakXrefs(o)
  1417.   {
  1418.     var aPaths = new Array("inetsdk:topic/content/seealso/xref");
  1419.     for (var i = 0; i < aPaths.length; i++)
  1420.     {
  1421.       var oSeeNodes = o.selectNodes(aPaths[i]);
  1422.       for (var i = 0; i < oSeeNodes.length; i++)
  1423.       {
  1424.         var oNode = oSeeNodes(i);
  1425.         oNode.setAttribute("enabled", "1");
  1426.       }
  1427.     }
  1428.   }
  1429.  
  1430.   function IsHex(s)
  1431.   {
  1432.     return s.match(/^0x/i) ? true : false;
  1433.   }
  1434.  
  1435.   // convert s to hexidecimal
  1436.   function toHex(s)
  1437.   {
  1438.     var sHexDigits = "0123456789ABCDEF", sResult = "";
  1439.  
  1440.     s = parseInt(s);
  1441.  
  1442.     while (s > 15)
  1443.     {
  1444.       i = s % 16;
  1445.       sResult = sHexDigits.charAt(i) + sResult;
  1446.       s = Math.floor(s/16);
  1447.     }
  1448.     sResult = sHexDigits.charAt(s) + sResult;
  1449.     return sResult;
  1450.   }
  1451.  
  1452.  
  1453.   // VB outputs values in decimal format.
  1454.   // In the lower pane of the object browser it outputs values >= 16 in decimal followed by (&Hxx)
  1455.   function VBOutput(s)
  1456.   {
  1457.     var iResult = parseInt(s);
  1458.     var sResult = "";
  1459.     sResult += iResult;
  1460.  
  1461.     // append the hex value if s is big enough
  1462.     if (iResult >= 16)
  1463.     {
  1464.       sResult += " '";
  1465.       if (IsHex(s))
  1466.       {
  1467.         sResult += s.replace(/^0x/i, '&H');
  1468.       }
  1469.       else
  1470.       {
  1471.         sResult += "&H" + toHex(iResult);
  1472.       }
  1473.     }
  1474.  
  1475.     return sResult;
  1476.   }
  1477.  
  1478.   Not currently in use
  1479.   // Strip the protocol from the beginning of the specified path.
  1480.   function StripProtocol(s)
  1481.   {
  1482.     return s.replace(/^((file|http):)?\/+([a-z]:)?/i, "")
  1483.   }
  1484.  
  1485.   // formerly used to handle building the VARIANT subtype string when resolving a dtype
  1486.   // Now we use pure script instead
  1487.   function IsSecond2Last(o)
  1488.   {
  1489.     var iSiblings = o.parentNode.childNodes.length;
  1490.     return (childNumber(o) == iSiblings-1) ? true : false;
  1491.   }
  1492.  
  1493.   */
  1494. ]]>
  1495.